﻿
#include "comm/comm_frame.h"

int comm_frame_send(int fd, uint8_t* buf, int len)
{
	comm_frame_send_context_t* ctx = (comm_frame_send_context_t*)fd;

	if ( ctx == NULL)
    {
		return -1;
	}

	if ( (len > COMM_FRAME_BUF_MAX_SIZE) || (buf == NULL) )
    {
		return -1;
	}

	if ( ctx->state != COMM_FRAME_SEND_READY)
    {
		// 正在发送
		return -1;
	}
	
	// 进入发送状态
	ctx->state = COMM_FRAME_SEND_BUSY;
	ctx->send_len_total = len;
	ctx->send_len_done = 0;
	ctx->send_len_now = 0;

	memcpy(ctx->frame_packet.sof, COMM_FRAME_PACKET_SOF, COMM_FRAME_PACKET_SOF_LEN);
	ctx->frame_packet.seq_no = ctx->seq_no;
	ctx->frame_packet.len_total = ctx->send_len_total;

	while ( ctx->send_len_done < ctx->send_len_total)
	{
		if ( ctx->send_len_total -  ctx->send_len_done > COMM_FRAME_PACKET_MAX_LEN)
        {
			ctx->send_len_now = COMM_FRAME_PACKET_MAX_LEN;
		} 
        else
        {
			ctx->send_len_now = ctx->send_len_total -  ctx->send_len_done;
		}

		ctx->frame_packet.len_done = ctx->send_len_done;
		ctx->frame_packet.len_now = ctx->send_len_now;
		ctx->frame_packet.crc16 = crc16((uint8_t *)&(ctx->frame_packet), COMM_FRAME_PACKET_HEAD_NO_CRC_LEN );

		memcpy(ctx->frame_packet.buf,
			buf + ctx->send_len_done,
			ctx->send_len_now);
        
		//发送
		int ret = sendto( ctx->upd_fd,
			(const char*)&ctx->frame_packet, 
			COMM_FRAME_PACKET_SEND_LEN(ctx->send_len_now),
			0,
			&(ctx->dest_addr),
			sizeof(ctx->dest_addr)
			);

		//printf("send to %s %d len %d\r\n", inet_ntoa(ctx->dest_addr.sin_addr), ntohs(app_global.config.send_port), ret);
		if(ret == -1)
		{
			printf("Comm frame sendto error: %s", strerror(errno));
			if(errno == ENOMEM)
				usleep(100);
		}


		// 更新已发送长度
		ctx->send_len_done += ctx->send_len_now;
	}

	// 发送结束
	ctx->seq_no++;
	ctx->state = COMM_FRAME_SEND_READY;
}

int comm_frame_do_recv(int fd, uint8_t* buf, int len)
{
	comm_frame_recv_context_t* ctx = (comm_frame_recv_context_t*)fd;
	
	return recvfrom( ctx->upd_fd, 
		(const char*)buf, 
		len,
		0,
		(sockaddr *)&(ctx->dest_addr),
		&(ctx->dest_addr_len)
		);
}

uint32_t GetTickCount()
{
	return 0;
}

int comm_frame_raw_check_new(comm_frame_recv_context_t* ctx)
{
	uint32_t timecount = GetTickCount();

	switch (ctx->state)
	{
	case COMM_FRAME_RECV_READY:
		{
			ctx->recv_len_total = ctx->frame_packet.len_total;

			if ( ctx->recv_len_total > COMM_FRAME_BUF_MAX_SIZE)
			{
				TRACE("\r\n 请求数据太大啦 len = %d", ctx->recv_len_total);

				return -1;
			}

			if ( ctx->frame_packet.len_done != 0 )
			{
				TRACE("\r\n 收到第一个包头，才开始新的包的接收");
				return -1;
			}

			if ( ctx->recv_buf != NULL)
			{
				TRACE("\r\n 出错啦，，之前应该先清除啊，， ");
				free(ctx->recv_buf);
				ctx->recv_buf = NULL;
			}

			ctx->recv_buf = (uint8_t*)malloc(sizeof(char)*(ctx->recv_len_total + COMM_PACKET_HEADER_SIZE) );

			if ( ctx->recv_buf == NULL)
			{
				TRACE("\r\n 出错啦，，内存申请失败，， ");
				exit(1);
			}

			ctx->recv_seq_no = ctx->frame_packet.seq_no;
			ctx->recv_len_done = 0;
			ctx->recv_timeout = timecount;
			ctx->state = COMM_FRAME_RECV_RECEIVING;
		}
		break;

	case COMM_FRAME_RECV_RECEIVING:
		{
			if (ctx->recv_seq_no == ctx->frame_packet.seq_no)
			{
				// 同一个FRAME包
				ctx->recv_timeout = timecount;
			}
			else
			{
				// 收到另一个包啦？？
				if ( timecount > ctx->recv_timeout)
				{
					if ( timecount - ctx->recv_timeout > COMM_FREAME_RECV_TIMEOUT_MICRO_SECOND)
					{
						ctx->state = COMM_FRAME_RECV_TIMEOUT;
						ctx->recv_timeout;

						// 就当接收完了吧
						comm_frame_raw_check_end(ctx);
					}
				}
			}
		}
		break;

	default:
		break;
	}
}

int comm_frame_raw_check_end(comm_frame_recv_context_t* ctx)
{
	if ( ctx->state == COMM_FRAME_RECV_RECEIVING)
	{
		if ( ctx->recv_len_done >= ctx->recv_len_total)
		{
			ctx->recv_buf->len = ctx->recv_len_total;
			//接收完啦
			ctx->state = COMM_FRAME_RECV_COMPLETE;

			comm_recv_done_cb();
			ctx->state = COMM_FRAME_RECV_READY;
		}
	}
	else if (ctx->state == COMM_FRAME_RECV_TIMEOUT)
	{
		ctx->recv_buf->len = ctx->recv_len_total;		

		comm_recv_done_cb();
		ctx->state = COMM_FRAME_RECV_READY;
	}
	
	
}

int comm_frame_recv(void* fd, uint8_t* buf, int len)
{
	comm_frame_recv_context_t* ctx = (comm_frame_recv_context_t*)fd;
	int cpy_len = 0;
	uint8_t* p_cpy_buf = 0;

	if ( ctx == NULL){
		return -1;
	}

	while (len)
	{
		switch(ctx->raw_state)
		{
		case COMM_FRAME_RECV_RAW_READY:
			{
				if (buf[0] == COMM_FRAME_PACKET_SOF_1)
				{
					ctx->frame_packet.sof[0] = buf[0];
					ctx->raw_len = 1; // 收到SOF头的一个字节啦
					
					ctx->raw_state = COMM_FRAME_RECV_RAW_SOF;
				}

				//读取一个字节
				len--;
				buf++;
			}
			break;

		case COMM_FRAME_RECV_RAW_SOF:
			{
				if ( len > (COMM_FRAME_PACKET_SOF_LEN - ctx->raw_len) )
				{
					cpy_len = COMM_FRAME_PACKET_SOF_LEN - ctx->raw_len;
				}
				else
				{
					cpy_len = len;
				}

				// 读取cpy_len个字节
				p_cpy_buf  = (uint8_t*)&(ctx->frame_packet.sof[0]);
				memcpy(p_cpy_buf + (ctx->raw_len), buf, cpy_len);

				len -= cpy_len;
				buf += cpy_len;
				ctx->raw_len += cpy_len;

				if ( ctx->raw_len == COMM_FRAME_PACKET_SOF_LEN)
				{
					if ( ( ctx->frame_packet.sof[1] == COMM_FRAME_PACKET_SOF_2)
						&& ( ctx->frame_packet.sof[2] == COMM_FRAME_PACKET_SOF_3)
						&& ( ctx->frame_packet.sof[3] == COMM_FRAME_PACKET_SOF_4) )
					{
						ctx->raw_len = 0; 
						ctx->raw_state = COMM_FRAME_RECV_RAW_HEADER;
					}
					else
					{
						ctx->raw_len = 0; 
						ctx->raw_state = COMM_FRAME_RECV_RAW_READY;
					}
				}
			}
			break;

		case COMM_FRAME_RECV_RAW_HEADER:
			{
				if ( len > (COMM_FRAME_PACKET_HEAD_RAW_LEN - ctx->raw_len) )
				{
					cpy_len = COMM_FRAME_PACKET_HEAD_RAW_LEN - ctx->raw_len;
				}
				else
				{
					cpy_len = len;
				}

				// 读取cpy_len个字节
				p_cpy_buf  = (uint8_t*)&(ctx->frame_packet.seq_no);
				memcpy(p_cpy_buf + (ctx->raw_len), buf, cpy_len);

				len -= cpy_len;
				buf += cpy_len;
				ctx->raw_len += cpy_len;

				if ( ctx->raw_len == COMM_FRAME_PACKET_HEAD_RAW_LEN)
				{
#if 1
					if ( ctx->frame_packet.crc16 
						== crc16((uint8_t *)&(ctx->frame_packet), COMM_FRAME_PACKET_HEAD_NO_CRC_LEN) ) // crc_check
#else
					if (1)
#endif
					{
						ctx->raw_len = 0; 
						ctx->raw_state = COMM_FRAME_RECV_RAW_DATA;

						comm_frame_raw_check_new(ctx);
					}
					else
					{
						ctx->raw_len = 0; 
						ctx->raw_state = COMM_FRAME_RECV_RAW_READY;
					}
				}
			}
			break;

		case COMM_FRAME_RECV_RAW_DATA:
			{
				if ( len > (ctx->frame_packet.len_now - ctx->raw_len) )
				{
					cpy_len = ctx->frame_packet.len_now - ctx->raw_len;
				}
				else
				{
					cpy_len = len;
				}

				// 读取cpy_len个字节
				if ( ctx->recv_buf != NULL)
				{
					p_cpy_buf = (uint8_t*)&(ctx->recv_buf->data[ctx->frame_packet.len_done]);
					memcpy(p_cpy_buf + (ctx->raw_len), buf, cpy_len);
				}
				
				len -= cpy_len;
				buf += cpy_len;
				ctx->raw_len += cpy_len;

				if ( ctx->raw_len == ctx->frame_packet.len_now)
				{
					// 这个小包接收完啦
					ctx->raw_len = 0;
					ctx->raw_state = COMM_FRAME_RECV_RAW_READY;

					ctx->recv_len_done += ctx->frame_packet.len_now;
					comm_frame_raw_check_end(ctx);
				}
			}
			break;

		default:
			break;
		}
	}
}

